package com.heima.comment.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.heima.comment.pojo.ApComment;
import com.heima.comment.pojo.ApCommentShow;
import com.heima.comment.service.ApCommentRepayService;
import com.heima.comment.service.ApCommentService;
import com.heima.comment.service.ApCommentShowService;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.threadlocal.UserThreadLocalUtils;
import com.heima.model.comment.dtos.CommentReplyLikeDto;
import com.heima.model.comment.dtos.CommentReplyLoadDTO;
import com.heima.model.comment.dtos.CommentReplyResponseDto;
import com.heima.model.comment.dtos.CommentReplySaveDto;
import com.heima.model.comment.enums.CommentTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * app评论回复
 *
 * @author Fuqiang
 * @since :2023-04-10
 */
@Slf4j
@Service
public class ApCommentRepayServiceImpl implements ApCommentRepayService {

    @Autowired
    ApCommentService commentService;

    @Autowired
    ApCommentShowService showService;

    /**
     * 保存app文章评论回复内容
     *
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(CommentReplySaveDto dto) {
        Integer userId = UserThreadLocalUtils.getUserIdAndCheckLogin();
        // 如果当前用户没有登录, 不允许回复评论
        if (userId <= 0) {
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }

        ApComment commentDB = commentService.getById(dto.getCommentId());
        if (commentDB == null) {
            log.error("要回复的评论不存在!");
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 保存评论回复信息
        commentService.save(this.buildReplyCommentToSave(dto, userId, commentDB));
        // 更新评论状态(评论数 +1)
        commentService.updateById(this.buildCommentToUpdate(commentDB));
        // 为展示表新增一条记录
        showService.saveOrUpdate(this.bulidCommentShowToSaveOrUpdate(commentDB));

    }

    /**
     * 为展示表新增一条记录 记录当前用户回复了这条评论
     *
     * @param commentDB
     * @return
     */
    private ApCommentShow bulidCommentShowToSaveOrUpdate(ApComment commentDB) {
        ApCommentShow commentShow = new ApCommentShow();
        commentShow.setCommentId(commentDB.getId());
        commentShow.setCommentUserId(UserThreadLocalUtils.getUserId());
        commentShow.setIsReply(true);
        return commentShow;
    }

    /**
     * 查询评论回复列表, 根据回复时间分页
     *
     * @param dto
     */
    @Override
    public List<CommentReplyResponseDto> load(CommentReplyLoadDTO dto) {
        Integer userId = UserThreadLocalUtils.getUserId();
        // 如果userId 小于0 则将userId置为null(认为是游客登录)
        if (userId != null && userId <= 0) {
            userId = null;
        }

        // 根据父评论id获取其全部留言的集合
        List<ApComment> apCommentList = getReplyCommentListByParentId(dto);

        // 转为DTO对象后返回
        return toCommentReplyResponseDTO(apCommentList);
    }

    private void timeHandler(CommentReplyLoadDTO dto) {
        long time = 20000000000000L;
        Date minDate = dto.getMinDate();
        if (minDate == null) {
            dto.setMinDate(new Date(time));
        }
        long minDateTime = dto.getMinDate().getTime();
        if (minDateTime == 20000000000000L) {
            return;
        }
        // 8小时
        minDateTime += 1000L * 60 * 60 * 8;
        dto.setMinDate(new Date(minDateTime));

    }

    /**
     * 根据父评论id获取其全部留言的集合
     *
     * @param dto
     * @return
     */
    private List<ApComment> getReplyCommentListByParentId(CommentReplyLoadDTO dto) {
        LambdaQueryWrapper<ApComment> queryWrapper = new LambdaQueryWrapper<>();
        // 评论的父id为当前id
        queryWrapper.eq(ApComment::getParentId, dto.getCommentId());
        queryWrapper.lt(dto.getMinDate() != null, ApComment::getCreateTime, dto.getMinDate());
        queryWrapper.eq(ApComment::getType, CommentTypeEnum.SUB.getValue());
        queryWrapper.orderByDesc(ApComment::getCreateTime);
        queryWrapper.last("limit 10");
        return commentService.list(queryWrapper);
    }

    /**
     * 将 apCommentList 转为  List<CommentReplyResponseDto>
     *
     * @param apCommentList
     * @return
     */
    private List<CommentReplyResponseDto> toCommentReplyResponseDTO(List<ApComment> apCommentList) {
        if (CollectionUtils.isEmpty(apCommentList)) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        return apCommentList.stream().map(apComment -> {
            CommentReplyResponseDto responseDto = new CommentReplyResponseDto();
            responseDto.setId(apComment.getId());
            responseDto.setAuthorId(apComment.getAuthorId());
            responseDto.setAuthorName(apComment.getAuthorName());
            responseDto.setEntryId(apComment.getEntryId());
            responseDto.setChannelId(null);
            responseDto.setContent(apComment.getCommentText());
            responseDto.setImages(apComment.getImages());
            responseDto.setLikes(apComment.getLikes());
            responseDto.setAddress(apComment.getAddress());
            responseDto.setReply(apComment.getReply());
            responseDto.setFlag(0);
            responseDto.setLatitude(apComment.getLatitude());
            responseDto.setLongitude(apComment.getLongitude());
            responseDto.setOrd(apComment.getOrd());
            responseDto.setCreatedTime(apComment.getCreateTime());
            responseDto.setOperation(showService.isLike(apComment.getId()) ? 0 : null);
            return responseDto;
        }).collect(Collectors.toList());
    }

    /**
     * 点赞或取消点赞
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Integer> like(CommentReplyLikeDto dto) {

        Integer userId = UserThreadLocalUtils.getUserIdAndCheckLogin();
        if (userId <= 0) {
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        ApComment commentDB = commentService.getById(dto.getCommentRepayId());
        if (commentDB == null) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 更新评论表
        Integer likes = dto.getOperation() == 0 ? commentDB.getLikes() + 1 : commentDB.getLikes() - 1;
        ApComment commentToUpdate = new ApComment();
        commentToUpdate.setId(dto.getCommentRepayId());
        commentToUpdate.setLikes(likes);
        commentService.updateById(commentToUpdate);
        // 更新展示表
        this.saveOrUpdateShow(dto, userId);

        Map<String, Integer> map = new HashMap<>(1);
        map.put("likes", likes);
        return map;
    }

    /**
     * 更新展示表
     *
     * @param dto
     * @param userId
     */
    private void saveOrUpdateShow(CommentReplyLikeDto dto, Integer userId) {
        LambdaQueryWrapper<ApCommentShow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApCommentShow::getCommentId, dto.getCommentRepayId());
        queryWrapper.eq(ApCommentShow::getCommentUserId, userId);
        ApCommentShow commentShow = showService.getOne(queryWrapper);
        if (commentShow == null) {
            commentShow = new ApCommentShow();
            commentShow.setCommentId(dto.getCommentRepayId());
            commentShow.setCommentUserId(userId);
            commentShow.setIsGiveUp(dto.getOperation() == 0);
            showService.save(commentShow);
        } else {
            commentShow.setIsGiveUp(dto.getOperation() == 0);
            showService.updateById(commentShow);
        }
    }

    /**
     * 构建修改评论信息的ApComment对象
     *
     * @param commentDB
     * @return
     */
    private ApComment buildCommentToUpdate(ApComment commentDB) {
        ApComment apComment = new ApComment();
        apComment.setId(commentDB.getId());
        apComment.setReply(commentDB.getReply() == null ? 1 : commentDB.getReply() + 1);
        return apComment;
    }

    /**
     * 构建一个子评论对象用于存库
     *
     * @param dto
     * @param userId
     * @param commentDB
     * @return
     */
    private ApComment buildReplyCommentToSave(CommentReplySaveDto dto, Integer userId, ApComment commentDB) {
        ApComment replyComment = new ApComment();
        replyComment.setArticleId(commentDB.getArticleId());
        replyComment.setCommentUserId(userId);
        replyComment.setCommentText(dto.getContent());
        replyComment.setLikes(0);
        replyComment.setReply(0);
        replyComment.setType(CommentTypeEnum.SUB.getValue());
        replyComment.setCreateTime(new Date());
        replyComment.setParentId(commentDB.getId());
        // 是否是粉丝因为关注没有落库, 所以起一个随机数进行模拟
        replyComment.setIsFans(new Random().nextInt(2));
        replyComment.setAuthorId(commentDB.getAuthorId());
        replyComment.setAuthorName(commentDB.getAuthorName());

        return replyComment;
    }

}
